// import com.alibaba.druid.sql.SQLUtils;
// import com.alibaba.druid.sql.ast.SQLExpr;
// import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
// import com.alibaba.druid.sql.dialect.oracle.ast.clause.PartitionExtensionClause;
// import com.alibaba.druid.sql.dialect.oracle.ast.clause.SampleClause;
// import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
// import com.alibaba.druid.sql.visitor.SQLASTVisitor;

#include "OracleSelectTableReference.h"
#include "../../../../SQLUtils.h"
#include "../../../../ast/SQLExpr.h"
#include "../../../../ast/SQLPivot.h"
#include "../../../../ast/SQLUnpivot.h"
#include "../clause/PartitionExtensionClause.h"
#include "../clause/SampleClause.h"
#include "../../visitor/OracleASTVisitor.h"
#include "../../../../visitor/SQLASTVisitor.h"
#include "../../../../../utils/instanceof.h"

OracleSelectTableReference::OracleSelectTableReference()
{
}

OracleSelectTableReference::OracleSelectTableReference(SQLExpr_ptr expr)
{
  this->setExpr(expr);
}

PartitionExtensionClause_ptr OracleSelectTableReference::getPartition()
{
  return partition;
}

void OracleSelectTableReference::setPartition(PartitionExtensionClause_ptr partition)
{
  if (partition != nullptr)
  {
    partition->setParent(SharedObject(OracleSelectTableReference));
  }
  this->partition = partition;
}

BOOL_ptr OracleSelectTableReference::isOnly()
{
  return this->only;
}

void OracleSelectTableReference::setOnly(BOOL_ptr only)
{
  this->only = only;
}

SampleClause_ptr OracleSelectTableReference::getSampleClause()
{
  return sampleClause;
}

void OracleSelectTableReference::setSampleClause(SampleClause_ptr sampleClause)
{
  if (sampleClause != nullptr)
  {
    sampleClause->setParent(SharedObject(OracleSelectTableReference));
  }
  this->sampleClause = sampleClause;
}

// @Override
void OracleSelectTableReference::accept0(SQLASTVisitor_ptr visitor)
{
  if (instanceof <SQLASTVisitor, OracleASTVisitor>(visitor))
  {
    this->accept0(std::dynamic_pointer_cast<OracleASTVisitor>(visitor));
  }
  else
  {
    SQLExprTableSource::accept0(visitor);
  }
}

void OracleSelectTableReference::accept0(OracleASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(OracleSelectTableReference)))
  {
    acceptChild(visitor, this->expr);
    acceptChild(visitor, this->partition);
    acceptChild(visitor, this->sampleClause);
    acceptChild(visitor, this->pivot);
    acceptChild(visitor, this->unpivot);
  }
  visitor->endVisit(SharedObject(OracleSelectTableReference));
}

// @Override
bool OracleSelectTableReference::equals(Object_ptr o)
{
  if (this == o.get())
  {
    return true;
  }
  if (o == nullptr || getClass() != o->getClass())
  {
    return false;
  }
  if (!SQLExprTableSource::equals(o))
  {
    return false;
  }

  OracleSelectTableReference_ptr that = std::dynamic_pointer_cast<OracleSelectTableReference>(o);

  if (only != that->only)
  {
    return false;
  }
  if (pivot != nullptr ? !pivot->equals(that->pivot) : that->pivot != nullptr)
  {
    return false;
  }
  if (unpivot != nullptr ? !unpivot->equals(that->unpivot) : that->unpivot != nullptr)
  {
    return false;
  }
  if (partition != nullptr ? !partition->equals(that->partition) : that->partition != nullptr)
  {
    return false;
  }
  if (sampleClause != nullptr ? !sampleClause->equals(that->sampleClause) : that->sampleClause != nullptr)
  {
    return false;
  }
  return flashback != nullptr ? flashback->equals(that->flashback) : that->flashback == nullptr;
}

// @Override
int OracleSelectTableReference::hashCode()
{
  int result = SQLExprTableSource::hashCode();
  result = 31 * result + (only ? 1 : 0);
  result = 31 * result + (pivot != nullptr ? pivot->hashCode() : 0);
  result = 31 * result + (unpivot != nullptr ? unpivot->hashCode() : 0);
  result = 31 * result + (partition != nullptr ? partition->hashCode() : 0);
  result = 31 * result + (sampleClause != nullptr ? sampleClause->hashCode() : 0);
  result = 31 * result + (flashback != nullptr ? flashback->hashCode() : 0);
  return result;
}

string_ptr OracleSelectTableReference::toString()
{
  return SQLUtils::toOracleString(SharedObject(OracleSelectTableReference));
}

SQLObject_ptr OracleSelectTableReference::clone()
{
  SQLObject_ptr clone_tmp = std::shared_ptr<OracleSelectTableReference>(new OracleSelectTableReference());
  std::shared_ptr<OracleSelectTableReference> x = std::dynamic_pointer_cast<OracleSelectTableReference>(clone_tmp);
  // OracleSelectTableReference x = new OracleSelectTableReference();
  cloneTo(x);

  x->only = only;

  if (pivot != nullptr)
  {
    x->setPivot(std::dynamic_pointer_cast<SQLPivot>(pivot->clone()));
  }

  if (unpivot != nullptr)
  {
    x->setUnpivot(std::dynamic_pointer_cast<SQLUnpivot>(unpivot->clone()));
  }

  if (partition != nullptr)
  {
    x->setPartition(std::dynamic_pointer_cast<PartitionExtensionClause>(partition->clone()));
  }

  if (sampleClause != nullptr)
  {
    x->setSampleClause(std::dynamic_pointer_cast<SampleClause>(sampleClause->clone()));
  }

  if (flashback != nullptr)
  {
    setFlashback(std::dynamic_pointer_cast<SQLExpr>(flashback->clone()));
  }

  return x;
}
